﻿using System.Collections.Generic;
using Core;
using UnityEditor;
using UnityEngine;
using UnityEngine.SceneManagement;

public class ExportScene
{
    [MenuItem("Assets/Mini Tools/Scene/导出场景")]
    private static void Main()
    {
        var objects = Selection.objects;

        for (var i = 0; i < objects.Length; ++i)
        {
            var curr = objects[i] as SceneAsset;
            if (curr == null) continue;

            EditorUtility.DisplayProgressBar("进度", $"正在导出{curr.name}场景", i * 1.0f / objects.Length);
            SplitSingleScene(curr);
        }

        EditorUtility.ClearProgressBar();
    }

    private static void SplitSingleScene(SceneAsset curr)
    {
        var name = curr.name;
        var cur_path = AssetDatabase.GetAssetPath(curr);

        var splits = new List<string>(cur_path.Split('/'));
        var game_name = splits.Find(c => c.StartsWith("g_"));

        var tgt_path = $"Assets/Proj/Games/{game_name}/Res/Scenes/{name}.unity";
        CheckDirIsExist(tgt_path);

        AssetDatabase.CopyAsset(cur_path, tgt_path);

        UnityEditor.SceneManagement.EditorSceneManager.OpenScene(tgt_path);
        var go = new GameObject(name);
        go.transform.position = Vector3.zero;
        go.transform.localScale = Vector3.one;
        go.transform.localRotation = Quaternion.identity;

        GameObject lighting = null;


        foreach (var obj in SceneManager.GetActiveScene().GetRootGameObjects())
        {
            if (obj.name == "NotOutPut")
            {
                continue;
            }

            if (obj.name == "Sys")
            {
                CollectUICameraInfo(obj, go);

                continue;
            }
            //if (obj.layer == LayerMask.NameToLayer("GroundNormal"))
            //{
            //    var box_collider = obj.GetComponent<BoxCollider>();
            //    if (box_collider != null)
            //    {
            //        box_collider.isTrigger = true;
            //    }
            //}
            //if (obj.name == "Reflection Probe")
            //{
            //    var probe = obj.GetComponent<ReflectionProbe>();
            //    probe.mode = UnityEngine.Rendering.ReflectionProbeMode.Custom;
            //    probe.customBakedTexture = RenderSettings.customReflection;
            //    continue;
            //}
            //if (obj.name == "Lights")
            //{
            //    lighting = obj;
            //    continue;
            //}
            //if (obj.name == "Directional Light")
            //{
            //    continue;
            //}

            if (obj.transform.parent == null && obj.hideFlags == HideFlags.None)
            {
                obj.transform.SetParent(go.transform);
            }
        }

        if (lighting == null)
        {
            lighting = new GameObject("Lights");
        }

        CollectLightmapInfo(lighting, go);

        //bool needDeleteScene = true;
        var lightmap_data = lighting.GetComponent<SceneLightmapData>();
        if (null != lightmap_data)
        {
            foreach (var data in lightmap_data.m_lightingInfos)
            {
                if (null != data.shadowMask)
                {
                    //needDeleteScene = false;
                    break;
                }
            }
        }

        //if (needDeleteScene)
        //{
        //    var obj = lighting.transform.Find("Bake");
        //    if (obj)
        //    {
        //        GameObject.DestroyImmediate(obj.gameObject);
        //    }

        //    lighting.transform.SetParent(go.transform);
        //    if (string.IsNullOrEmpty(deleteContent))
        //    {
        //        deleteContent = tgt_path;
        //    }
        //    else
        //    {
        //        deleteContent += $"\n {tgt_path}";
        //    }
        //}

        var tgt_prefab_path = $"Assets/Proj/Games/{game_name}/Res/Prefabs/Scene/{name}.prefab";

        CheckDirIsExist(tgt_prefab_path);

        PrefabUtility.SaveAsPrefabAssetAndConnect(go, tgt_prefab_path, InteractionMode.UserAction);
        GameObject.DestroyImmediate(go);

        var not_output_go = GameObject.Find("NotOutPut");
        if (not_output_go != null)
        {
            GameObject.DestroyImmediate(not_output_go);
        }

        AssetDatabase.SaveAssets();
        UnityEditor.SceneManagement.EditorSceneManager.SaveOpenScenes();
        //if (needDeleteScene)
        //{
        //    AssetDatabase.DeleteAsset(tgt_path);
        //    UnityEditor.SceneManagement.EditorSceneManager.OpenScene(cur_path);
        //    //Debug.Log($"场景 {name} 导出成功,无阴影效果,删除场景{tgt_path}");
        //}
        Debug.Log($"场景 {name} 导出成功");
    }

    private static void CollectUICameraInfo(GameObject sys, GameObject go)
    {
        var ui_cam = sys.transform.Find("Camera")?.GetComponent<Camera>();
        if (ui_cam == null)
        {
            return;
        }

        var data = go.AddComponent<SceneUICameraData>();
        data.Enabled = ui_cam.enabled;
        data.ClearFlags = ui_cam.clearFlags;
        data.BackgroundColor = ui_cam.backgroundColor;
        data.CullingMask = ui_cam.cullingMask;
        data.Orthographic = ui_cam.orthographic;
        data.FieldOfView = ui_cam.fieldOfView;
    }

    private static void CollectLightmapInfo(GameObject lights, GameObject go)
    {
        var lightmap_data = lights.AddComponent<SceneLightmapData>();
        var render_data = go.AddComponent<SceneRenderData>();

        List<SceneLightmapData.LightingInfo> lighting_list = new List<SceneLightmapData.LightingInfo>();
        var rendererInfos = new List<SceneRenderData.RendererInfo>();

        List<Texture2D> lightmaps = new List<Texture2D>();

        var renderers = go.GetComponentsInChildren<MeshRenderer>();
        foreach (MeshRenderer renderer in renderers)
        {
            if (renderer.lightmapIndex != -1)
            {
                var info = new SceneRenderData.RendererInfo();
                info.renderer = renderer;
                info.lightmapIndex = renderer.lightmapIndex;
                info.lightmapOffsetScale = renderer.lightmapScaleOffset;

                var lightmapData = LightmapSettings.lightmaps[renderer.lightmapIndex];

                info.lightmapIndex = lightmaps.IndexOf(lightmapData.lightmapColor);
                if (info.lightmapIndex == -1)
                {
                    info.lightmapIndex = lightmaps.Count;
                    lightmaps.Add(lightmapData.lightmapColor);
                    lighting_list.Add(new SceneLightmapData.LightingInfo(lightmapData.lightmapDir,
                        lightmapData.lightmapColor, lightmapData.shadowMask));
                }

                rendererInfos.Add(info);
            }
        }

        render_data.m_RendererInfo = rendererInfos.ToArray();

        lightmap_data.m_lightingInfos = lighting_list.ToArray();
        lightmap_data.LightProbes = LightmapSettings.lightProbes;
        lightmap_data.lightmapsMode = LightmapSettings.lightmapsMode;
        lightmap_data.skybox = RenderSettings.skybox;
        lightmap_data.ambientMode = RenderSettings.ambientMode;
        lightmap_data.ambientSkyColor = RenderSettings.ambientSkyColor;
        lightmap_data.ambientEquatorColor = RenderSettings.ambientEquatorColor;
        lightmap_data.ambientGroundColor = RenderSettings.ambientGroundColor;
        lightmap_data.defaultReflectionMode = RenderSettings.defaultReflectionMode;
#if UNITY_2022_OR_NEWER
        lightmap_data.customReflection = RenderSettings.customReflectionTexture;
#else
        lightmap_data.customReflection = RenderSettings.customReflection;
#endif
        lightmap_data.reflectionBounces = RenderSettings.reflectionBounces;
        lightmap_data.reflectionIntensity = RenderSettings.reflectionIntensity;
        lightmap_data.fogDensity = RenderSettings.fogDensity;
        lightmap_data.fogColor = RenderSettings.fogColor;
        lightmap_data.fogMode = RenderSettings.fogMode;
        lightmap_data.fogEndDistance = RenderSettings.fogEndDistance;
        lightmap_data.fogStartDistance = RenderSettings.fogStartDistance;
        lightmap_data.fog = RenderSettings.fog;
    }

    private static void CheckDirIsExist(string tgt_path)
    {
        var full_path = System.IO.Path.Combine(Application.dataPath, tgt_path.Replace(@"Assets/", ""));
        Utils.File.CreateDirectoryByFilePath(full_path);

        if (System.IO.File.Exists(full_path))
        {
            AssetDatabase.DeleteAsset(tgt_path);
        }
    }
}
